package com.niiwoo.civet.mobile.controller.invest;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSONObject;
import com.niiwoo.civet.mobile.util.MoneyUtil;
import com.niiwoo.civet.mobile.vo.common.LinkageConfig;
import com.niiwoo.civet.mobile.vo.request.invest.AutoInvestSettingRequestVO;
import com.niiwoo.civet.mobile.vo.request.invest.BatchInvestRequestVO;
import com.niiwoo.civet.mobile.vo.response.invest.AutoInvestSettingInfoResponseVO;
import com.niiwoo.civet.mobile.vo.response.invest.BatchInvestSettingInfoResponseVO;
import com.niiwoo.civet.trade.constant.TradeRedisKey;
import com.niiwoo.civet.trade.dto.common.InvestEvaluationDTO;
import com.niiwoo.civet.trade.dto.common.PeriodValue;
import com.niiwoo.civet.trade.dto.common.SysInvestConfigDTO;
import com.niiwoo.civet.trade.dto.request.AutoInvestSettingRequestDTO;
import com.niiwoo.civet.trade.dto.request.BatchInvestRequestDTO;
import com.niiwoo.civet.trade.dto.response.UserAutoInvestConfigDTO;
import com.niiwoo.civet.trade.dto.response.UserBatchInvestConfigDTO;
import com.niiwoo.civet.trade.enums.LoanTypeEnum;
import com.niiwoo.civet.trade.service.invest.AutoInvestDubboService;
import com.niiwoo.civet.trade.service.invest.InvestDubboService;
import com.niiwoo.civet.user.dto.response.DataStatusResponseDTO;
import com.niiwoo.civet.user.dto.response.UserIdentityInfoResponseDTO;
import com.niiwoo.civet.user.enums.UserDataStatusEnum;
import com.niiwoo.civet.user.enums.UserDataTypeEnum;
import com.niiwoo.civet.user.enums.UserForbidTypeEnum;
import com.niiwoo.civet.user.service.UserAuthorizationInfoDubboService;
import com.niiwoo.civet.user.service.UserForbidDubboService;
import com.niiwoo.civet.user.service.UserIdentityDubboService;
import com.niiwoo.civet.user.service.UserStatusDubboService;
import com.niiwoo.tripod.base.enums.UserTypeEnum;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.component.AccessRateLimiter;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.util.RequestUtil;
import com.niiwoo.tripod.web.vo.Empty;
import com.niiwoo.tripod.web.vo.Result;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequestMapping("/userInvest")
@Api(tags = "自动投资/批量投资(刘春)", description = "/userInvest")
@Slf4j
public class UserInvestByAutoController {

	@Reference(version = "1.0.0")
	private AutoInvestDubboService autoInvestDubboService;
	@Reference(version = "1.0.0")
	private UserForbidDubboService userForbidDubboService;
	@Reference(version = "1.0.0")
	private UserAuthorizationInfoDubboService userAuthorizationInfoDubboService;
	@Reference(version = "1.0.0")
	private UserStatusDubboService userStatusDubboService;
	@Reference(version = "1.0.0")
	private InvestDubboService investDubboService;
	@Reference(version = "1.0.0")
	private UserIdentityDubboService userIdentityDubboService;
	@Value("${h5-auto-invest-commission-auth-url}")
	private String h5AutoInvestCommissionAuthUrl;

	@Value("${h5-invest-risk-tips-url}")
	private String h5InvestRiskTipsUrl;
	// 极速借个人
	@Value("${h5-fastloan-contract-url}")
	private String h5FastloanContractUrl;
	@Autowired
	private AccessRateLimiter accessRateLimiter;
	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@PostMapping("/autoInvestSetting")
	@ApiOperation("自动投资设置 (张万里/刘春)")
	public Empty autoInvestSetting(@RequestBody @Valid AutoInvestSettingRequestVO request) {
		// 精度处理
		request.setMinKeepBalance(MoneyUtil.scale2HalfUp(request.getMinKeepBalance()));
		request.setSingleMaxInvestAmount(MoneyUtil.scale2HalfUp(request.getSingleMaxInvestAmount()));
		request.setUseCouponMinInvestAmount(MoneyUtil.scale2HalfUp(request.getUseCouponMinInvestAmount()));
		String userId = String.valueOf(PrincipalContext.getUserId());
		wholeHundred(request.getSingleMaxInvestAmount(), "TRD10021");
		// 加息最低使用金额必须在开启红包的时候才需要校验
		if (Objects.nonNull(request.getAutoUsePrize()) && Byte.valueOf("1").equals(request.getAutoUsePrize())) {
			wholeHundred(request.getUseCouponMinInvestAmount(), "TRD10022");
		}

		// 判断行为禁止
		userForbidDubboService.validUserForbidInfo(userId, UserForbidTypeEnum.INVESTOR);
		// 检查投资人电子签章，没有签章则需要发起签章请求
		DataStatusResponseDTO dataStatusResponseDTO = userStatusDubboService.getByUserIdAndType(userId, UserDataTypeEnum.FADADA_AUTHORIZE);
		if (dataStatusResponseDTO == null || !UserDataStatusEnum.FadadaStatus.PASS_CERTIFIED.getStatus().equals(dataStatusResponseDTO.getDataStatus())) {
			userAuthorizationInfoDubboService.fadadaAuth(userId);
		}
		InvestEvaluationDTO investEvaluationDTO = investDubboService.getInvestEvaluationInfo(userId);
		if (investEvaluationDTO.getSurplusCanInvestAmount() != null
				// 风险投资剩余可投金额大于100才可以
				&& investEvaluationDTO.getSurplusCanInvestAmount().compareTo(BigDecimal.valueOf(100)) < 0) {
			// 当前投资金额已达该风险类型投资上限
			throw new BizException("TRD10017");
		}
		AutoInvestSettingRequestDTO requestDTO = new AutoInvestSettingRequestDTO();
		requestDTO.setUserId(userId);
		requestDTO.setSingleMaxInvestAmount(request.getSingleMaxInvestAmount());
		requestDTO.setMinKeepBalance(request.getMinKeepBalance());
		requestDTO.setIsAutoUsePrize(request.getAutoUsePrize());
		if (request.getAutoUsePrize() != null && request.getAutoUsePrize().intValue() == 1) {
			requestDTO.setIsMustUsePrize(request.getMustUsePrize());
		} else {
			requestDTO.setIsMustUsePrize((byte) 0);
		}
		requestDTO.setUseCouponMinInvestAmount(request.getUseCouponMinInvestAmount());
		requestDTO.setProductTypes(request.getProductTypes());
		requestDTO.setRatetTypes(request.getRatetTypes());
		requestDTO.setRepaymentTypes(request.getRepaymentTypes());
		List<com.niiwoo.civet.trade.dto.common.PeriodValue> periodValues = new ArrayList<>();
		requestDTO.setPeriodTypes(periodValues);
		for (LinkageConfig.PeriodValue periodValue : request.getPeriodTypes()) {
			com.niiwoo.civet.trade.dto.common.PeriodValue period = new com.niiwoo.civet.trade.dto.common.PeriodValue();
			period.setDeadline(periodValue.getDeadline());
			period.setDeadlineUnit(periodValue.getDeadlineUnit());
			periodValues.add(period);
		}
		autoInvestDubboService.applyAutoInvestSetting(requestDTO);
		return Empty.getInstance();
	}

	@PostMapping(value = "/getAutoInvestSettingInfo")
	@ApiOperation("获取自动投资设置详情 (张万里/刘春)")
	public Result<AutoInvestSettingInfoResponseVO> getAutoInvestSettingInfo() throws Exception {
		String userId = String.valueOf(PrincipalContext.getUserId());
		Future<UserIdentityInfoResponseDTO> identityFuture = RpcContext.getContext().asyncCall(() -> userIdentityDubboService.get(userId));
		// 从trade服务中查询用户的自动投资配置
		UserAutoInvestConfigDTO configDTO = autoInvestDubboService.queryUserAutoInvestConfig(userId);
		AutoInvestSettingInfoResponseVO responseVO = new AutoInvestSettingInfoResponseVO();
		if (Objects.isNull(configDTO)) {
			return Result.with(responseVO);
		}
		// 系统配置列表
		List<LinkageConfig> linkageConfigs = generateSystemAutoInvestConfig(configDTO.getSysConfigList());
		responseVO.setLinkageConfigs(linkageConfigs);
		// 用户配置
		UserAutoInvestConfigDTO.UserConfig userConfigDTO = configDTO.getUserConfig();
		AutoInvestSettingInfoResponseVO.UserConfig userConfigVO = new AutoInvestSettingInfoResponseVO.UserConfig();
		responseVO.setEnableAuto((byte) 0);
		responseVO.setReadFlag(configDTO.getReadFlag());// 是否已读
		responseVO.setMinInvestAmount(configDTO.getMinInvestAmount());// 起投金额
		if (Byte.valueOf("0").equals(configDTO.getReadFlag())) {
			RpcContext.getContext().asyncCall(() -> autoInvestDubboService.updateReadFalg(userId));
		}
		if (userConfigDTO != null) {
			responseVO.setEnableAuto(userConfigDTO.getEnabled());
			userConfigVO.setSingleMaxInvestAmount(userConfigDTO.getSingleMaxInvestAmount());
			userConfigVO.setMinKeepBalance(userConfigDTO.getMinKeepBalance());
			userConfigVO.setAutoUsePrize(userConfigDTO.getAutoUsePrize());
			userConfigVO.setMustUsePrize(userConfigDTO.getMustUsePrize());
			userConfigVO.setUseCouponMinInvestAmount(userConfigDTO.getUseCouponMinInvestAmount());
			userConfigVO.setProductTypes(userConfigDTO.getProductTypes());
			userConfigVO.setRatetTypes(userConfigDTO.getRatetTypes());
			userConfigVO.setRepaymentTypes(userConfigDTO.getRepaymentTypes());

			// 期限封装
			if (CollectionUtils.isNotEmpty(userConfigDTO.getPeriodTypes())) {
				List<LinkageConfig.PeriodValue> periodValueVo = new ArrayList<>();
				userConfigVO.setPeriodTypes(periodValueVo);
				for (PeriodValue periodValue : userConfigDTO.getPeriodTypes()) {
					LinkageConfig.PeriodValue value = new LinkageConfig.PeriodValue();
					periodValueVo.add(value);
					value.setDeadline(periodValue.getDeadline());
					value.setDeadlineUnit(periodValue.getDeadlineUnit());
				}
			}
			responseVO.setUserConfig(userConfigVO);

		}
		UserIdentityInfoResponseDTO identityDTO = identityFuture.get();
		responseVO.defaultConfig().singleMax(configDTO.getDefaultConfig().getSingleMaxInvestAmount()).minKeep(configDTO.getDefaultConfig().getMinKeepBalance())
				.useCouponMin(configDTO.getDefaultConfig().getUseCouponMinInvestAmount());
		responseVO.contract().investContract(h5FastloanContractUrl + "?type=autoInvest")
				.riskTips(identityDTO == null ? h5InvestRiskTipsUrl : h5InvestRiskTipsUrl + URLEncoder.encode(identityDTO.getName(), "utf-8")).authorizeAgreement(h5AutoInvestCommissionAuthUrl);
		return Result.with(responseVO);
	}

	/**
	 * 生成自动投资/批量投资联动配置
	 * 
	 * @param sysConfigList
	 * @return
	 */
	private List<LinkageConfig> generateSystemAutoInvestConfig(List<SysInvestConfigDTO> sysConfigList) {
		List<LinkageConfig> configs = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(sysConfigList)) {
			for (SysInvestConfigDTO investConfig : sysConfigList) {
				LinkageConfig linkageConfig = new LinkageConfig();
				// 标的类型
				LinkageConfig.Product product = new LinkageConfig.Product();
				linkageConfig.setProductType(product);
				product.setName(LoanTypeEnum.enumOf(investConfig.getLoanType()).getDesc());
				product.setValue(investConfig.getLoanType());
				// 期限
				LinkageConfig.Period period = new LinkageConfig.Period();
				linkageConfig.setPeriodType(period);

				period.setDeadline(investConfig.getPeriod());
				period.setDeadlineUnit(investConfig.getPeriodType());
				period.setName(investConfig.getPeriod() + (Byte.valueOf("1").equals(investConfig.getPeriodType()) ? "个月" : "天"));
				// 利率
				LinkageConfig.Rate rate = new LinkageConfig.Rate();
				linkageConfig.setRateType(rate);
				rate.setValue(investConfig.getRateBegin());
				rate.setName(investConfig.getRateBegin().multiply(BigDecimal.valueOf(100)).stripTrailingZeros().toPlainString() + "%");
				// 还款方式
				LinkageConfig.Repayment repayment = new LinkageConfig.Repayment();
				linkageConfig.setRepaymentType(repayment);
				repayment.setName(com.niiwoo.civet.trade.enums.RepaymentTypeEnum.enumOf(investConfig.getRepaymentType()).getDesc());
				repayment.setValue(investConfig.getRepaymentType());
				configs.add(linkageConfig);
			}
		}
		return configs;
	}

	@PostMapping("/disableAutoInvest")
	@ApiOperation("关闭自动投资设置 (张万里/刘春)")
	public Empty disableAutoInvest() {
		autoInvestDubboService.disableAutoInvest(String.valueOf(PrincipalContext.getUserId()));
		return Empty.getInstance();
	}

	@PostMapping(value = "/getBatchInvestSettingInfo")
	@ApiOperation("获取批量投资设置详情 (张万里/刘春)")
	public Result<BatchInvestSettingInfoResponseVO> getBatchInvestSettingInfo() throws Exception {
		String userId = String.valueOf(PrincipalContext.getUserId());
		// Future<UserIdentityInfoResponseDTO> identityFuture =
		// RpcContext.getContext().asyncCall(() ->
		// userIdentityDubboService.get(userId));
		UserBatchInvestConfigDTO configDTO = autoInvestDubboService.queryUserBatchInvestConfig(userId);
		BatchInvestSettingInfoResponseVO responseVO = new BatchInvestSettingInfoResponseVO();
		if (Objects.isNull(configDTO)) {
			return Result.with(responseVO);
		}
		// 系统配置列表
		List<LinkageConfig> inkageConfigs = generateSystemAutoInvestConfig(configDTO.getSysConfigList());
		responseVO.setLinkageConfigs(inkageConfigs);
		responseVO.setEnableAuto(configDTO.getEnableAuto());
		responseVO.setMinInvestAmount(configDTO.getMinInvestAmount());// 起投金额
		UserBatchInvestConfigDTO.UserConfig userConfigDTO = configDTO.getUserConfig();
		// 生成用户配置
		generateUserBatchConfig(userConfigDTO, responseVO);

		// UserIdentityInfoResponseDTO identityDTO = identityFuture.get();
		responseVO.defaultConfig().singleMax(configDTO.getDefaultConfig().getSingleMaxInvestAmount()).minKeep(configDTO.getDefaultConfig().getMinKeepBalance())
				.useCouponMin(configDTO.getDefaultConfig().getUseCouponMinInvestAmount());
		responseVO.contract().investContract(h5FastloanContractUrl + "?type=batchInvest").riskTips(h5InvestRiskTipsUrl).authorizeAgreement(h5AutoInvestCommissionAuthUrl);
		// .riskTips(identityDTO == null ? h5InvestRiskTipsUrl : h5InvestRiskTipsUrl +
		// URLEncoder.encode(identityDTO.getName(),
		// "utf-8")).authorizeAgreement(h5AutoInvestCommissionAuthUrl);
		return Result.with(responseVO);
	}

	@PostMapping(value = "/getBatchInvestSettingInfoForPc")
	@ApiOperation("PC获取批量投资设置详情 (刘春)")
	@AuthIgnore
	public Result<BatchInvestSettingInfoResponseVO> getBatchInvestSettingInfoForPc() throws Exception {
		String userId = String.valueOf(PrincipalContext.getUserId());
		log.info("PC访问批量投资配置详情，用户id{}", userId);
		UserBatchInvestConfigDTO configDTO = autoInvestDubboService.queryUserBatchInvestConfig(userId);
		BatchInvestSettingInfoResponseVO responseVO = new BatchInvestSettingInfoResponseVO();
		if (Objects.isNull(configDTO)) {
			return Result.with(responseVO);
		}
		// 系统配置列表
		List<LinkageConfig> inkageConfigs = generateSystemAutoInvestConfig(configDTO.getSysConfigList());
		responseVO.setLinkageConfigs(inkageConfigs);
		UserBatchInvestConfigDTO.UserConfig userConfigDTO = configDTO.getUserConfig();
		// 生成用户配置
		generateUserBatchConfig(userConfigDTO, responseVO);
		responseVO.defaultConfig().singleMax(configDTO.getDefaultConfig().getSingleMaxInvestAmount()).minKeep(configDTO.getDefaultConfig().getMinKeepBalance())
				.useCouponMin(configDTO.getDefaultConfig().getUseCouponMinInvestAmount());
		responseVO.contract().investContract(h5FastloanContractUrl + "?type=batchInvest").riskTips(h5InvestRiskTipsUrl).authorizeAgreement(h5AutoInvestCommissionAuthUrl);
		return Result.with(responseVO);
	}

	private void generateUserBatchConfig(UserBatchInvestConfigDTO.UserConfig userConfigDTO, BatchInvestSettingInfoResponseVO responseVO) {
		if (Objects.isNull(userConfigDTO)) {
			return;
		}
		BatchInvestSettingInfoResponseVO.UserConfig userConfigVO = new BatchInvestSettingInfoResponseVO.UserConfig();
		userConfigVO.setSingleMaxInvestAmount(userConfigDTO.getSingleMaxInvestAmount());
		userConfigVO.setMinKeepBalance(userConfigDTO.getMinKeepBalance());
		userConfigVO.setAutoUsePrize(userConfigDTO.getAutoUsePrize());
		userConfigVO.setMustUsePrize(userConfigDTO.getMustUsePrize());
		userConfigVO.setUseCouponMinInvestAmount(userConfigDTO.getUseCouponMinInvestAmount());
		userConfigVO.setSyncToAutoInvest(userConfigDTO.getSyncToAutoInvest());
		userConfigVO.setProductTypes(userConfigDTO.getProductTypes());
		userConfigVO.setRatetTypes(userConfigDTO.getRatetTypes());
		userConfigVO.setRepaymentTypes(userConfigDTO.getRepaymentTypes());
		// 期限封装
		if (CollectionUtils.isNotEmpty(userConfigDTO.getPeriodTypes())) {
			List<LinkageConfig.PeriodValue> periodValueVo = new ArrayList<>();
			userConfigVO.setPeriodTypes(periodValueVo);
			for (PeriodValue periodValue : userConfigDTO.getPeriodTypes()) {
				LinkageConfig.PeriodValue value = new LinkageConfig.PeriodValue();
				periodValueVo.add(value);
				value.setDeadline(periodValue.getDeadline());
				value.setDeadlineUnit(periodValue.getDeadlineUnit());
			}
		}
		responseVO.setUserConfig(userConfigVO);
	}

	@PostMapping("/batchInvest")
	@ApiOperation("批量投资 (张万里/刘春)")
	public Empty batchInvest(@RequestBody @Valid BatchInvestRequestVO request) {
		// 精度处理
		request.setMinKeepBalance(MoneyUtil.scale2HalfUp(request.getMinKeepBalance()));
		request.setSingleMaxInvestAmount(MoneyUtil.scale2HalfUp(request.getSingleMaxInvestAmount()));
		request.setUseCouponMinInvestAmount(MoneyUtil.scale2HalfUp(request.getUseCouponMinInvestAmount()));
		String userId = String.valueOf(PrincipalContext.getUserId());
		UserTypeEnum usertype = PrincipalContext.getUserPrincipal().getUserType();
		if (Objects.isNull(usertype)) {
			usertype = UserTypeEnum.PERSONAL;
		}
		wholeHundred(request.getSingleMaxInvestAmount(), "TRD10021");
		// 加息最低使用金额必须在开启红包的时候才需要校验
		if (Objects.nonNull(request.getAutoUsePrize()) && Byte.valueOf("1").equals(request.getAutoUsePrize())) {
			wholeHundred(request.getUseCouponMinInvestAmount(), "TRD10022");
		}
		// 判断行为禁止
		userForbidDubboService.validUserForbidInfo(userId, UserForbidTypeEnum.INVESTOR);
		// 检查投资人电子签章，没有签章则需要发起签章请求
		DataStatusResponseDTO dataStatusResponseDTO = userStatusDubboService.getByUserIdAndType(userId, UserDataTypeEnum.FADADA_AUTHORIZE);
		if (dataStatusResponseDTO == null || !UserDataStatusEnum.FadadaStatus.PASS_CERTIFIED.getStatus().equals(dataStatusResponseDTO.getDataStatus())) {
			if (usertype == UserTypeEnum.ORGANIZATION) {
				userAuthorizationInfoDubboService.fadadaEnterAuth(userId);
			} else {
				userAuthorizationInfoDubboService.fadadaAuth(userId);
			}
		}
		InvestEvaluationDTO investEvaluationDTO = investDubboService.getInvestEvaluationInfo(userId);
		if (investEvaluationDTO.getSurplusCanInvestAmount() != null && investEvaluationDTO.getSurplusCanInvestAmount().compareTo(BigDecimal.ZERO) == 0) {
			// 当前投资金额已达该风险类型投资上限
			throw new BizException("TRD10017");
		}
		boolean limit = accessRateLimiter.userLimit(userId, "batch-invest", 1, AccessRateLimiter.Unit.MINUTE, 2);
		if (limit) {
			throw new BizException("SYS1001"); // 亲爱的用户，您操作频率过快，请稍后再试
		}
		BatchInvestRequestDTO requestDTO = new BatchInvestRequestDTO();
		requestDTO.setUserId(userId);
		requestDTO.setSingleMaxInvestAmount(request.getSingleMaxInvestAmount());
		requestDTO.setMinKeepBalance(request.getMinKeepBalance());
		requestDTO.setIsAutoUsePrize(request.getAutoUsePrize());
		if (request.getAutoUsePrize() != null && request.getAutoUsePrize().intValue() == 1) {
			requestDTO.setIsMustUsePrize(request.getMustUsePrize());
		} else {
			requestDTO.setIsMustUsePrize((byte) 0);
		}
		requestDTO.setUseCouponMinInvestAmount(request.getUseCouponMinInvestAmount());
		requestDTO.setSyncToAutoInvest(request.getSyncToAutoInvest());
		requestDTO.setProductTypes(request.getProductTypes());
		requestDTO.setRatetTypes(request.getRatetTypes());
		requestDTO.setRepaymentTypes(request.getRepaymentTypes());
		List<com.niiwoo.civet.trade.dto.common.PeriodValue> periodValues = new ArrayList<>();
		requestDTO.setPeriodTypes(periodValues);
		for (LinkageConfig.PeriodValue periodValue : request.getPeriodTypes()) {
			com.niiwoo.civet.trade.dto.common.PeriodValue period = new com.niiwoo.civet.trade.dto.common.PeriodValue();
			period.setDeadline(periodValue.getDeadline());
			period.setDeadlineUnit(periodValue.getDeadlineUnit());
			periodValues.add(period);
		}
		// 设置投资人的身份标志
		requestDTO.setUserType(usertype.getValue());
		autoInvestDubboService.batchInvest(requestDTO);
		return Empty.getInstance();
	}

	private void wholeHundred(BigDecimal amount, String exception) {
		BigDecimal zero = BigDecimal.ZERO;
		if (Objects.nonNull(amount)) {
			BigDecimal[] num = amount.divideAndRemainder(BigDecimal.valueOf(100));
			if (zero.compareTo(num[1]) != 0) {
				throw new BizException(exception);
			}
		}
	}
	// 初次上线使用，后续看情况开放
	// @ApiOperation(value = "重新加载自动投资人队列(全部队列初始化!!!慎用)", hidden = true)
	// @PostMapping("/importReloadAllAutoInvestorQueue")
	// @AuthIgnore
	// public Empty reloadAllAutoInvestorQueue(HttpServletRequest request) {
	//
	// autoInvestDubboService.reloadAllAutoInvestorQueue();
	// return Empty.getInstance();
	// }

	@ApiOperation(value = "重新加载自动投资人队列(休息区人员回归)", hidden = true)
	@PostMapping("/reloadAutoInvestorQueue")
	@AuthIgnore
	public Empty reloadAutoInvestorQueue(HttpServletRequest request) {
		log.info("主动调用休息区回归操作，ip{}", RequestUtil.getUserRealIP(request));
		autoInvestDubboService.reloadAutoInvestorQueue();
		return Empty.getInstance();
	}

	@ApiOperation(value = "查看自动投资队列", hidden = true)
	@PostMapping("/investorQueue/inspect")
	@AuthIgnore
	public Result<JSONObject> inspectInvestorQueue(@RequestParam(defaultValue = "auto-investors") String view) {
		JSONObject json = new JSONObject();
		Set<String> keys = redisTemplate.keys(TradeRedisKey.AUTO_INVESTORS_QUEUE_PREFIX + "*");
		for (String key : keys) {
			Set<ZSetOperations.TypedTuple<String>> tupleSet = redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, -1);
			List<Map<String, Object>> list = tupleSet.stream().map(tuple -> {
				Map<String, Object> map = new HashMap<>();
				map.put("user_id", tuple.getValue());
				map.put("priority", tuple.getScore());
				return map;
			}).collect(Collectors.toList());
			Map<String, Object> map = new HashMap<>();
			map.put("list", list);
			map.put("size", list.size());
			json.put(key, map);
		}
		Set<String> noRedEnvelopes = redisTemplate.opsForZSet().range(TradeRedisKey.REST_AREA_NO_RED_ENVELOPES, 0, -1);
		if (CollectionUtils.isNotEmpty(noRedEnvelopes)) {
			json.put("NO_RED_ENVELOPES", noRedEnvelopes);
		}
		Set<String> notSufficientFunds = redisTemplate.opsForZSet().range(TradeRedisKey.REST_AREA_NOT_SUFFICIENT_FUNDS, 0, -1);
		if (CollectionUtils.isNotEmpty(notSufficientFunds)) {
			json.put("NOT_SUFFICIENT_FUNDS", notSufficientFunds);
		}
		Set<String> riskFund = redisTemplate.opsForZSet().range(TradeRedisKey.REST_AREA_RISK_FUND, 0, -1);
		if (CollectionUtils.isNotEmpty(riskFund)) {
			json.put("RISK_FUND", riskFund);
		}
		Set<String> unknow = redisTemplate.opsForZSet().range(TradeRedisKey.REST_AREA_UNKNOW, 0, -1);
		if (CollectionUtils.isNotEmpty(unknow)) {
			json.put("UNKNOW", unknow);
		}

		return Result.with(json);
	}

	// 初次上线使用，后续不使用
	// @ApiOperation(value = "初始化数据", hidden = true)
	// @PostMapping("/autoInvestDataInti")
	// @AuthIgnore
	// public Empty autoInvestDataInti() {
	// autoInvestDubboService.dataTransfer();
	// return Empty.getInstance();
	// }

}
